package cz.boxdesign.library.web;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import cz.boxdesign.library.common.dao.CommonObjectDao;
import cz.boxdesign.library.entity.Address;
import cz.boxdesign.library.entity.Book;
import cz.boxdesign.library.entity.Publisher;
import cz.boxdesign.library.service.BookService;
import cz.boxdesign.library.service.PublisherService;
import cz.boxdesign.library.web.validation.PublisherValidator;
import cz.boxdesign.library.web.view.BookView;
import cz.boxdesign.library.web.view.PublisherView;

@Controller
@RequestMapping("/publisher")
public class PublisherController {

	@Autowired
	@Qualifier("publisherService")
	private PublisherService publisherService;

	@Autowired
	@Qualifier("knihaService")
	private BookService bookService;

	@Autowired
	CommonObjectDao commonObjectDao;

	@InitBinder
	public void initModel(WebDataBinder binder) {
		Object targer = binder.getTarget();
		if (targer instanceof BookView) {
			if (binder.getValidator() == null) {
				binder.setValidator(new PublisherValidator());
			}
		}
	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView showList() {
		ModelAndView model = new ModelAndView("publisher/showList");
		model.addObject("publisherList", publisherService.getAll());
		model.addObject("publisherView", new PublisherView());
		return model;
	}

	@RequestMapping(value = "/show", method = RequestMethod.GET)
	public ModelAndView show(@RequestParam("publisherId") Integer publisherId) {
		ModelAndView model = new ModelAndView("publisher/show");
		Publisher p = publisherService.getById(publisherId);
		PublisherView view = new PublisherView();
		copyToView(p, view);
		List<Book> bookList = bookService.getByClause("and id_n=" + publisherId);
		model.addObject("publisher", view);
		model.addObject("bookList", bookList);
		return model;
	}

	@RequestMapping("/edit")
	public ModelAndView edit(@RequestParam("publisherId") Integer publisherId, HttpServletRequest request) {
		ModelAndView model = request.getAttribute("user") != null ? (ModelAndView) request.getAttribute("user") : new ModelAndView();
		model.setViewName("publisher/edit");
		insertOrUpdate(model, publisherId);
		return model;
	}

	@RequestMapping("/new")
	public ModelAndView newPublisher(HttpServletRequest request) {
		ModelAndView model = request.getAttribute("user") != null ? (ModelAndView) request.getAttribute("user") : new ModelAndView();
		insertOrUpdate(model, -1);
		return model;
	}

	@RequestMapping("/find")
	public ModelAndView find(PublisherView view) {
		ModelAndView model = new ModelAndView("publisher/showList");
		model.addObject("publisherList", publisherService.getByClause("and nazev_n like '" + view.getNazev() + "'"));
		return model;
	}

	@RequestMapping(value = "/submit", method = RequestMethod.POST)
	public ModelAndView submit(@RequestParam("publisherId") Integer publisherId, PublisherView view, HttpServletRequest request,
			BindingResult error) {
		ModelAndView model = new ModelAndView();
		List<Error> errorList = validate(view, publisherId);
		if (errorList.isEmpty() && !error.hasErrors()) {
			Publisher p = new Publisher();
			if (null != publisherId) { // update
				p = publisherService.getById(publisherId);
				p.setId(p.getId());
				Address a = new Address();
				a.setMesto(view.getMesto());
				a.setPsc(view.getPsc());
				a.setUlice(view.getUlice());
				p.setAddress(a);
				publisherService.updateEntity(p);
				return new ModelAndView(new RedirectView("show.do?publisherId=" + publisherId));
			} else { // insert
				copyFromView(p, view);
				publisherService.insertEntity(p);
				Publisher inserted = publisherService.getByClause("and nazev_n ='" + p.getNazev() + "'").get(0);
				return new ModelAndView(new RedirectView("show.do?publisherId=" + inserted.getId()));
			}
		} else {
			HttpSession session = request.getSession();
			model.addObject("errorList", errorList);
			model.addObject("error", error);
			if (publisherId != null) {
				session.setAttribute("model", model);
				return new ModelAndView(new RedirectView("edit.do?publisherId=" + publisherId));
			} else {
				model.addObject("view", view);
				session.setAttribute("model", model);
				return new ModelAndView(new RedirectView("new.do"));
			}
		}
	}

	private List<Error> validate(PublisherView view, Integer publisherId) {
		List<Error> errorList = new ArrayList<Error>();
		if (!commonObjectDao.isPublisherNameAvailable(view.getNazev()) && publisherId == null) {
			errorList.add(new Error("Name Of Publisher is Not available. Please use another one."));
		}
		String psc = view.getPsc();
		if (psc.contains(" ")) {
			psc = psc.replace(" ", "");
		}
		try {
			Integer pscint = Integer.valueOf(psc);
			if (view.getPsc().length() > 6) {
				errorList.add(new Error("error.psc.wrong.format"));
			}
		} catch (NumberFormatException e) {
			errorList.add(new Error("error.psc.wrong.format"));
		}
		return errorList;
	}

	private void insertOrUpdate(ModelAndView model, Integer publisherId) {
		if (publisherId != -1) {
			Publisher p = publisherService.getById(publisherId);
			PublisherView view = new PublisherView();
			copyToView(p, view);
			model.addObject("publisher", view);
		} else {
			model.addObject("publisher", new PublisherView());
		}

	}

	private void copyToView(Publisher p, PublisherView view) {
		view.setId(p.getId());
		view.setNazev(p.getNazev());
		view.setMesto(p.getAddress().getMesto());
		view.setPsc(p.getAddress().getPsc());
		view.setUlice(p.getAddress().getUlice());
	}

	private void copyFromView(Publisher p, PublisherView view) {
		p.setId(p.getId());
		p.setNazev(p.getNazev());
		Address a = new Address();
		a.setMesto(view.getMesto());
		a.setPsc(view.getPsc());
		a.setUlice(view.getUlice());
		p.setAddress(a);
	}
}
